#include "db_base.h"
#include <assert.h>
#include <spdlog/spdlog.h>
#include <spdlog/fmt/fmt.h>
#include <charconv>
// #include <boost/json/src.hpp>

DBValue::DBValue(std::string_view value)
    :value_(value)
{}

DBValue::operator double() const
{
    double d;
    std::from_chars(value_.data(), value_.data()+value_.size(), d);
    return d;
}

DBValue::operator float() const
{
    float d;
    std::from_chars(value_.data(), value_.data()+value_.size(), d);
    return d;
}

DBValue::operator bool() const
{
    // std::cout << value_.data() << std::endl;
    return atoi(value_.data()) != 0;
}

DBValue::operator int() const
{
    return atoi(value_.data());
}

DBValue::operator uint32_t() const
{
    return std::stoul(value_.data());
}

DBValue::operator const char*() const
{
    return value_.data();
}

DBValue::operator std::string() const
{
    return value_.data();
}

DBValue::operator std::string_view() const
{
    return value_;
}

DBValue::operator boost::gregorian::date() const
{
    return boost::gregorian::from_string(value_.data());
}

DBValue::operator boost::posix_time::ptime() const
{
    SPDLOG_ERROR("{}", value_.data());
    // return boost::posix_time::from_iso_extended_string(value_.data());
    return boost::posix_time::time_from_string(value_.data());
}

DBRow::DBRow(const std::unordered_map<std::string, int> &column_index, std::vector<std::string_view> &&row)
    : column_index_(column_index)
    , row_(row)
{
}

DBValue DBRow::operator[](std::string_view column_name) const
{
    auto iter = column_index_.find(column_name.data());
    if (iter == column_index_.end()) {
        SPDLOG_ERROR("column {} not found", column_name);
        assert(false);
    }
    return DBValue(row_[iter->second]);
}

DBValue DBRow::operator()(std::string_view column_name, std::string_view default_value) const
{
    auto iter = column_index_.find(column_name.data());
    if (iter == column_index_.end()) {
        return DBValue(default_value);
    }
    return DBValue(row_[iter->second]);
}

void tag_invoke(const boost::json::value_from_tag&, boost::json::value& jv, DBRow const &obj)
{
    jv = boost::json::value_from(obj.row_);
}
